package com.rim.samples.device.helloworlddemo;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;
import net.rim.device.api.system.CoverageInfo;
import net.rim.device.api.system.RadioInfo;

public class MyDataSource extends ByteArrayInputStream
{

    private String TAG = "MyDataSource";

    private byte[] mData;

    private int mDataTail = 0;
    
    private int mPacketSize;

    private DatagramConnection mConnection;

    private Datagram mPacket;
    
    private boolean isFirstRead = true;
    
    private byte[] packetData;
    
    public MyDataSource(byte[] buf)
    {
        super(buf);
        mData = buf;
        
        try
        {
            mConnection = createDatagramCnx(38858);
            mPacket = mConnection.newDatagram(mConnection.getMaximumLength());
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    
    public synchronized int available()
    {
        int re = super.available();
        Log.d(TAG, "available()" + "return:" + Integer.MAX_VALUE);
        return Integer.MAX_VALUE;
    }

    public synchronized void close() throws IOException
    {
        Log.d(TAG, "close()");
        super.close();
    }

    public void mark(int readAheadLimit)
    {
        Log.d(TAG, "mark(int readAheadLimit)");
        super.mark(readAheadLimit);
    }

    public boolean markSupported()
    {
        Log.d(TAG, "markSupported()");
        return super.markSupported();
    }

    public synchronized int read()
    {
        int re = super.read();
        Log.d(TAG, "read()" + " return:" + re);
        return re;
    }

    public synchronized int _read(byte[] b, int offset, int length)
    {
        Log.d("read", "read: to b , lenght:" + length + " offset:" + offset
            + " time: " + System.currentTimeMillis());
        Log.d("read", "b.length:" + b.length + " offset:" + offset + " length:"
            + length);
        
        
        if ((mDataTail + length) < mData.length)
        {
            System.arraycopy(mData, mDataTail, b, offset, length);
            mDataTail += length;
            Log.d("read", "total:" + mDataTail);
            return length;
        }
        else
        {
            length = mData.length - mDataTail;
            System.arraycopy(mData, mDataTail, b, offset, length);
            mDataTail = 0;
            Log.d("read", "loop again");
            return length;
        }
    }

    private DatagramConnection createDatagramCnx(int port) throws IOException
    {
        String url = "datagram://:" + port;
        if ((CoverageInfo.getCoverageStatus(RadioInfo.WAF_WLAN, true) & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT)
        {
            url += "/ ;interface=wifi";
        }
        return (DatagramConnection) Connector.open(url/* , Connector.READ, true */);
    }
    
    public synchronized int read(byte[] b, int offset, int length)
    {
        Log.d(TAG, "in read:" + " offset=" + offset + " length=" + length
            + " time=" + System.currentTimeMillis());

        int readSize = 0;
        // read a whole packet
        try
        {
            if(isFirstRead)
            {
                packetData = new byte[length];
                isFirstRead = false;
            }
            else 
            {
                mConnection.receive(mPacket);
                packetData = mPacket.getData();
            }
        }
        catch (Exception e)
        {
            Log.d(TAG, "receive mPacket Exception:" + e.toString());
            e.printStackTrace();
        }

        //mPacketSize = mPacket.getLength();
        mPacketSize = packetData.length;

        if (length <= mPacketSize)
        {
            readSize = length;
        }
        else
        {
            readSize = mPacketSize;
        }
        System.arraycopy(packetData, 0, b, offset, readSize);

        return readSize;
    }
    
    public synchronized void reset()
    {
        Log.d(TAG, "reset()");
        super.reset();
    }

    public synchronized long skip(long n)
    {
        long re = super.skip(n);
        Log.d(TAG, "long skip(long n)" + " arg:" + "n=" + n + "  return: " + re);
        return re;
    }

    public int read(byte[] arg0) throws IOException
    {
        int re = super.read(arg0);
        Log.d(TAG, "read(byte[] arg0)" + " arg:" + " arg0=" + arg0
            + "  return:" + re);
        return re;
    }

}
